package com.da.print;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.ServletException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.da.landlord.DaChargeBill;
import com.da.landlord.DaChargeBillRecord;
import com.da.landlord.DaChargeItem;
import com.da.landlord.DaChargeItemService;
import com.da.landlord.DaRoom;
import com.da.landlord.DaSuite;
import com.da.landlord.DaSuiteService;
import com.googlecode.cswish.model.PageInfo;
import com.googlecode.cswish.struts.spring.GenericService;
import com.googlecode.cswish.util.bean.ModelUtil;
import com.ra.landlord.Fee;
import com.ra.landlord.FeeAddition;
import com.ra.landlord.FeeRecord;
import com.ra.landlord.FeeRecordService;
import com.ra.landlord.FeeService;
import com.ra.landlord.Room;
import com.ra.landlord.RoomService;
import com.ra.util.DateTimeUtil;

@Service
public class BatchPrintService {

	@Autowired
	private DaSuiteService daSuiteService;
	
	@Autowired
	private RoomService raRoomService;
	
	@Autowired
	private GenericService genericService;
	
	@Autowired
	private DaChargeItemService chargeItemService;
	
	@Autowired
	private FeeService feeService;
	
	@Autowired
	private FeeRecordService feeRecordService;
	
	public PageInfo<DaRoom> searchDaRoom(DaSuite model, String tenantUserName, Integer chargeState, Integer expiredLeave) {
		if (chargeState == null) {
			chargeState = 0; 	//已缴费， 默认
		}
		model.setRentState(DaSuite.RENTSTATE_RENTED);
		return daSuiteService.searchRoom(model, tenantUserName, chargeState, expiredLeave);
	}
	
	public PageInfo<Room> searchRaRoom(Room model, String tenantUserName, Integer chargeState, Integer expiredLeave) {
		if (chargeState == null) {
			chargeState = 0; 	//已缴费， 默认
		}
		model.setRentState(Room.RENT_STATE_ALREADY);
		return raRoomService.searchRoomsNew(model, tenantUserName, chargeState, expiredLeave);
	}
	
	public List<DaChargeBill> printDaFee(List<DaSuite> models, Integer chargeState) {
		List<DaChargeBill> daChargeBills = new ArrayList<DaChargeBill>(models.size() * 2);
		if (chargeState == 0) {	//已缴费
			for (DaSuite suite : models) {
				DaSuite dbSuite = genericService.load(suite);
				if (DaSuite.RENT_TYPE_ENTIRE.equals(dbSuite.getRentType())) {
					DaChargeBill latestChargeBill = dbSuite.getRooms().get(0).getAgreement().getChargeBills().get(0); 
					daChargeBills.add(latestChargeBill);
					if (dbSuite.getRooms().get(0).getAgreement().getChargeBills().size() > 1) {
						latestChargeBill.setPrevBalance(dbSuite.getRooms().get(0).getAgreement().getChargeBills().get(1).getBalance());
					}
				} else {
					for (DaRoom room : dbSuite.getRentRooms()) {
						if (room.getAgreement() != null && room.getAgreement().getChargeBills() != null && room.getAgreement().getChargeBills().size() > 0 && DateTimeUtil.GetDateWithAdvanceNum(room.getAgreement().getChargeBills().get(0).getChargeItems().get(0).getDateEndRecv(), room.getAgreement().getAdvanceNum()).compareTo(DateTimeUtil.throwTimeForDate(new Date())) >= 0) {
							DaChargeBill latestChargeBill = room.getAgreement().getChargeBills().get(0); 
							daChargeBills.add(latestChargeBill);
							if (room.getAgreement().getChargeBills().size() > 1) {
								latestChargeBill.setPrevBalance(room.getAgreement().getChargeBills().get(1).getBalance());
							}
						}
					}
				}
			}
		} else {	//未缴费
			for (DaSuite suite : models) {
				DaSuite dbSuite = genericService.load(suite);
				if (DaSuite.RENT_TYPE_ENTIRE.equals(dbSuite.getRentType())) {
					DaChargeBill chargeBill = new DaChargeBill();
					chargeBill.setChargeItems(chargeItemService.getOrGenerateChargeBillRecord(dbSuite.getRooms().get(0)).getChargeItems());
					chargeBill.setBalance(BigDecimal.valueOf(0));
					chargeBill.setRoom(dbSuite.getRooms().get(0));
					if (dbSuite.getRooms().get(0).getChargeBills() != null && dbSuite.getRooms().get(0).getChargeBills().size() > 0) {
						chargeBill.setPrevBalance(dbSuite.getRooms().get(0).getChargeBills().get(0).getBalance());
					}
					countPriceAmount(chargeBill);
					daChargeBills.add(chargeBill);
				} else {
					for (DaRoom room : dbSuite.getRentRooms()) {
						if (room.getAgreement() != null && (room.getAgreement().getChargeBills() == null || room.getAgreement().getChargeBills().size() == 0 || DateTimeUtil.GetDateWithAdvanceNum(room.getAgreement().getChargeBills().get(0).getChargeItems().get(0).getDateEndRecv(), room.getAgreement().getAdvanceNum()).compareTo(DateTimeUtil.throwTimeForDate(new Date())) < 0)) {
							DaChargeBill chargeBill = new DaChargeBill();
							chargeBill.setChargeItems(chargeItemService.getOrGenerateChargeBillRecord(room).getChargeItems());
							chargeBill.setBalance(BigDecimal.valueOf(0));
							chargeBill.setRoom(room);
							if (room.getChargeBills() != null && room.getChargeBills().size() > 0) {
								chargeBill.setPrevBalance(dbSuite.getRooms().get(0).getChargeBills().get(0).getBalance());
							}
							countPriceAmount(chargeBill);
							daChargeBills.add(chargeBill);
						}
					}
				}
			}
			
		}
		return daChargeBills;
	}
	
	private void countPriceAmount(DaChargeBill model) {
		BigDecimal amountRecv = BigDecimal.valueOf(0);
		for (DaChargeItem chargeItem: model.getChargeItems()) {
			amountRecv = amountRecv.add(chargeItem.getPriceRecv());
		}
		model.setAmountRecv(amountRecv);
		model.setAmountActual(amountRecv);
	}
	
	public List<Fee> printRaFee(List<Room> models, Integer chargeState) {
		List<Fee> fees = new ArrayList<Fee>(models.size() * 2);
		if (chargeState == 0) {
			//已缴费
			for (Room room : models) {
				Room dbRoom = genericService.load(room);
				if (Room.RENT_TYPE_ENTIRE.equals(dbRoom.getRentType())) {
					Fee latestFee = dbRoom.getAgreement().getFees().get(0);
					fees.add(latestFee);
					if (dbRoom.getAgreement().getFees().size() > 1) {
						latestFee.setPrevBalance(dbRoom.getFees().get(1).getBalance());
					} else {
						latestFee.setPrevBalance(BigDecimal.valueOf(0));
					}
					if (latestFee.getAgreement() != null && latestFee.getAgreement().getRentBeginDate().equals(latestFee.getDateBeginRecv()) && latestFee.getAgreement().getRentEndDate().equals(latestFee.getDateEndRecv())) {
						latestFee.setDeposite(true);
					} else {
						latestFee.setDeposite(false);
						List<FeeAddition> feeAddtions = latestFee.getFeeAdditions();
						BigDecimal amountActual = BigDecimal.valueOf(0);
						for (FeeAddition feeAddition : feeAddtions) {
							amountActual = amountActual.add(feeAddition.getPriceActual());
						}
						latestFee.setRentAmountActual(latestFee.getAmountRecv().subtract(amountActual).add(latestFee.getPrevBalance()));
						latestFee.setRentAmountRecv(latestFee.getRental());
					}
				} else {
					//TODO 处理subroom
				}
			}
		} else {
			//未缴费
			for (Room room : models) {
				Room dbRoom = genericService.load(room);
				if (Room.RENT_TYPE_ENTIRE.equals(dbRoom.getRentType())) {
					Fee fee = new Fee();
					fees.add(fee);
					feeRecordService.copyFeeRecord2Fee(feeService.getOrGenerateFeeRecordIfNotExists(dbRoom.getAgreement()), fee);
					fee.setId(null);
					if (dbRoom.getAgreement().getFees().size() > 0) {
						fee.setPrevBalance(dbRoom.getFees().get(0).getBalance());
					}
					if (dbRoom.getAgreement().getFees().size() == 0) {
						fee.getRoom().setNeedAddDeposit(true);
						if (fee.getAmountActual() == null) {
							fee.setAmountActual(fee.getAmountRecv().add(BigDecimal.valueOf(Double.valueOf(fee.getRoom().getAgreement().getDeposit()))));
						}
						fee.setDeposite(false); //这里没意义，要同时产生租金和押金
					} else {
						fee.getRoom().setNeedAddDeposit(false);
						fee.setDeposite(false);
					}
					fee.setRentAmountRecv(BigDecimal.valueOf(Double.valueOf(dbRoom.getRental())));
					fee.setRentAmountActual(BigDecimal.valueOf(Double.valueOf(dbRoom.getRental())));
				} else {
					//TODO 处理subroom
				}
			}
		}
		return fees;
	}
	
	
	public List<Fee> printOneRaFee(Fee model, boolean isDeposit, BigDecimal prevBalance) throws ServletException, IOException {
		List<Fee> fees = new ArrayList<Fee>();
		Fee dbFee = genericService.load(model);
		dbFee.setDeposite(isDeposit);
		dbFee.setPrevBalance(prevBalance);
		if (!isDeposit) {
			List<FeeAddition> feeAddtions = dbFee.getFeeAdditions();
			BigDecimal amountActual = BigDecimal.valueOf(0);
			for (FeeAddition feeAddition : feeAddtions) {
				amountActual = amountActual.add(feeAddition.getPriceActual());
			}
			dbFee.setRentAmountActual(dbFee.getAmountRecv().subtract(amountActual).add(prevBalance));
			dbFee.setRentAmountRecv(dbFee.getRental());
		}
		fees.add(dbFee);
		return fees;
	}
	
	public List<Fee> printOneRaFeeRecord(FeeRecord model, boolean needAddDeposit, BigDecimal prevBalance) throws ServletException, IOException {
		List<Fee> fees = new ArrayList<Fee>();
		Fee dbFee = new Fee();
		FeeRecord dbFeeRecord = genericService.load(model);
		feeRecordService.copyFeeRecord2Fee(dbFeeRecord, dbFee);
		dbFee.setId(null);
		dbFee.getRoom().setNeedAddDeposit(needAddDeposit);
		if (needAddDeposit && dbFee.getAmountActual() == null) {
			dbFee.setAmountActual(dbFee.getAmountRecv().add(BigDecimal.valueOf(Double.valueOf(dbFee.getRoom().getAgreement().getDeposit()))));
		}
		
		dbFee.setPrevBalance(prevBalance);
		dbFee.setRentAmountActual(dbFee.getRental());
		if (dbFee.getRentalCalc() != null) {
			dbFee.setRentAmountRecv(dbFee.getRentalCalc());
		} else {
			List<FeeAddition> feeAddtions = dbFee.getFeeAdditions();
			BigDecimal amountRecv = BigDecimal.valueOf(0);
			if (feeAddtions != null) {
				for (FeeAddition feeAddition : feeAddtions) {
					amountRecv = amountRecv.add(feeAddition.getPriceRecv());
				}
			}
			dbFee.setRentAmountRecv(dbFee.getAmountRecv().subtract(amountRecv).add(prevBalance));
		}
		
		fees.add(dbFee);
		return fees;
	}
	
	public List<DaChargeBill> printOneDaFee(DaChargeBill model, BigDecimal prevBalance) throws ServletException, IOException {
		List<DaChargeBill> chargeBills = new ArrayList<DaChargeBill>();
		DaChargeBill dbChargeBill = genericService.load(model);
		dbChargeBill .setPrevBalance(prevBalance);
		chargeBills.add(dbChargeBill);
		return chargeBills;
	}
	
	public List<DaChargeBill> printOneDaChargeBillRecord(DaChargeBillRecord model, BigDecimal prevBalance) throws ServletException, IOException {
		List<DaChargeBill> chargeBills = new ArrayList<DaChargeBill>();
		DaChargeBill dbChargeBill = new DaChargeBill();
		DaChargeBillRecord dbChargeBillRecord = genericService.load(model);
		ModelUtil.copy(dbChargeBillRecord, dbChargeBill, true);
		dbChargeBill.setId(null);
		dbChargeBill.setPrevBalance(prevBalance);
		chargeBills.add(dbChargeBill);
		return chargeBills;
	}
}
